﻿using System;
using System.Data;

namespace FluentSql
{
    public class ScalarFluentSqlCommand : BaseFluentSqlCommand, IScalarFluentSqlCommand
    {
        #region Public Methods

        public T ExecuteScalar<T>(Func<object, T> iDeserialize)
        {
            if (KeepConnection)
            {
                return ExecuteScalarImpl(Context.PersistentConnection, iDeserialize);
            }
            else
            {
                using (var connection = Context.CreateConnection())
                {
                    return ExecuteScalarImpl(connection, iDeserialize);
                }
            }
        }

        private T ExecuteScalarImpl<T>(IDalSqlConnection iConnection, Func<object, T> iDeserialize)
        {
            using (var transaction = iConnection.BeginTransaction(IsolationLevel))
            {
                object rawResult = null;
                using (var command = transaction.CreateCommand(CommandType, Command))
                {
                    SerializeParameters?.Invoke(command);
                    rawResult = command.ExecuteScalar();
                }
                transaction.Commit();
                return iDeserialize(rawResult);
            }
        }

        public IScalarFluentSqlCommand SetCommand(string iCommand)
        {
            SetCommandImpl(iCommand);
            return this;
        }

        public IScalarFluentSqlCommand SetCommandType(CommandType iCommandType)
        {
            SetCommandTypeImpl(iCommandType);
            return this;
        }

        public IScalarFluentSqlCommand SetContext(IDalContext iContext)
        {
            SetContextImpl(iContext);
            return this;
        }

        public IScalarFluentSqlCommand SetIsolationLevel(IsolationLevel iIsolationLevel)
        {
            SetIsolationLevelImpl(iIsolationLevel);
            return this;
        }

        public IScalarFluentSqlCommand SetKeepConnection(bool iKeepConnection)
        {
            SetKeepConnectionImpl(iKeepConnection);
            return this;
        }

        public IScalarFluentSqlCommand SetParameters(Action<IDalSqlCommand> iSerializeParameters)
        {
            SetParameters(iSerializeParameters);
            return this;
        }

        #endregion Public Methods
    }
}
